home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / Xprof / xprof / parse.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  18KB  |  625 lines

  1. /*==================================================================
  2.  *      File :          parse.c
  3.  *      Package:        Xprof
  4.  *
  5.  *      Author :        Aloke Gupta.
  6.  *
  7.  *  (C) Copyright 1992, Aloke Gupta.
  8.  *==================================================================*/
  9.  
  10. /* parse.c
  11.  *
  12.  * Parse the input file containing information on sizes and speeds of 
  13.  * the Xlib requests
  14.  *
  15.  * Each input line is of the form:
  16.  * Request_Name Attr_1=<> ... Attr_N=< > (Size_1, Speed_1) ... (Size_N, Speed_N)
  17.  *
  18.  * Multiple specifications may be given for each request, for different sizes.
  19.  * A '#' sign marks of comments. All lines that begin with a '#' are ignored and
  20.  * all characters following a '#; are ignored too.
  21.  * Functions:
  22.  *    1.  parse_parameters(FILE *fp)
  23.  *    2.  init_msgcost();
  24.  *    3.  fill_win_cost(int index, char **strptrptr)
  25.  *    4.  fill_gfx_cost(int index, char **strptrptr)
  26.  *    5.  fill_txt_cost(int index, char **strptrptr)
  27.  *    6.  insert_costcell(CostCell **costlist, float size, float speed)
  28.  *    7.  get_request_time(int index, Xattributes *attributes)
  29.  *    8.  CostCell *allocCostCell(float size, float speed)
  30.  *    9.  printlist(CostCell *costlist)
  31.  *    10. get_db_linewidth_index(int lw, Install install)
  32.  *      11. get_db_closest_lw(int lw)
  33.  *    11. get_db_fontname_index(char *fontname, Install install)
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include "common.h"
  38. #include "profile.h"
  39.  
  40. extern MsgType RequestType[];    /* Defined in table.c */
  41. MsgCost msgcost[MAXREQUESTS];
  42.  
  43. CostCell *allocCostCell(/* size, speed*/);
  44.  
  45. static double net_latency = 0.0;    /* Network latency in milliseconds */
  46. static double net_speed   = MAXDOUBLE;    /* Network speed in bytes per second */
  47. static int    linenum=0;        /* linenumber in init file */
  48.  
  49. void   set_net_latency(latency) double latency; { net_latency = latency; }
  50. void   set_net_speed  (speed  ) double speed  ; { net_speed = speed    ; }
  51. double get_net_latency(       )            { return net_latency   ; }
  52. double get_net_speed  (       )           { return net_speed     ; }
  53.  
  54. /*
  55.  * Parse the initialization file to obtain the costs of each request
  56.  */
  57. parse_parameters(fp)
  58. FILE *fp;
  59. {
  60.     char   req_name[80];
  61.     char   in_string[MAXSTRINGSIZE];
  62.     char   *strptr, *tmpptr ;
  63.     int    req_num;
  64.     double dtmp;
  65.  
  66.     /* 
  67.      * Initialize the msgcost array to NULLs
  68.      */
  69.     init_msgcost();
  70.  
  71.     /*
  72.      * Now scan the initialization file
  73.      */
  74.     while( fgets(in_string, MAXSTRINGSIZE, fp) != NULL) {
  75.     linenum++;
  76.     strptr = in_string;
  77.     while (isspace(*strptr)) strptr++; /* Eat the leading white space */
  78.     if (*strptr == '#') continue;       /* Ignore comment lines */
  79.     if ((tmpptr = strchr(strptr, '#')) != NULL)
  80.         *tmpptr = '\0';           /* Ignore all that follows a # */
  81.  
  82.     if (sscanf(strptr, "%s", req_name) != 1)
  83.             continue;
  84.     /* Check if this is information about the network */
  85.     if (t_search(strptr, "Network Latency")) {
  86.         tmpptr = strptr + strlen("Network Latency");
  87.         if (sscanf(tmpptr, "%lf", &dtmp) != 1)
  88.         fprintf(stderr, "line %3d: Insufficient arguments\n", linenum);
  89.         else set_net_latency(dtmp);
  90.         continue;
  91.     }
  92.     if (t_search(strptr, "Network Speed")) {
  93.         tmpptr = strptr + strlen("Network Speed");
  94.         if (sscanf(tmpptr, "%lf", &dtmp) != 1)
  95.         fprintf(stderr, "line %3d: Insufficient arguments\n", linenum);
  96.         else {
  97.            if (dtmp > 0)
  98.           set_net_speed(1000.0*dtmp);    /*Convert to bytes per second*/
  99.            else fprintf(stderr,"Network speed must be more than zero !!\n");
  100.         }
  101.         continue;
  102.     }
  103.     /*
  104.      * Check if this is a legal request
  105.      */
  106.     if ((req_num = lookup_request(req_name) ) == 0) {
  107.         fprintf(stderr,"line %3d: Unknown request: %s\n",linenum,req_name);
  108.         continue;
  109.     }
  110.     /*
  111.      * Update the data structures for this request, by entering the
  112.      * request in the appropriate location.
  113.      */
  114.     switch(RequestType[req_num].msgclass) {
  115.       case WIN:
  116.         fill_win_cost(req_num, &strptr);
  117.         break;
  118.       case GFX:
  119.         fill_gfx_cost(req_num, &strptr);
  120.         break;
  121.       case TXT:
  122.         fill_txt_cost(req_num, &strptr);
  123.         break;
  124.       default:
  125.         break;
  126.     }
  127.     }
  128.     return(0);
  129. }
  130.  
  131. init_msgcost() {
  132.     int i, j;
  133.  
  134.     for (i = 0; i < MAXREQUESTS; i++) {
  135.     switch (RequestType[i].msgclass) {
  136.       case WIN:        /* Windowing request */
  137.         msgcost[i].win = NULL;
  138.         break;
  139.       case GFX:        /* Graphics request */
  140.         msgcost[i].gfx = (GfxCost *) malloc(GFXSLOTS * sizeof(GfxCost));
  141.         for (j = 0; j < GFXSLOTS; j++) {
  142.         /*
  143.         msgcost[i].gfx[j].linewidth = 0;
  144.         */
  145.         msgcost[i].gfx[j].costlist  = NULL;
  146.         }
  147.         break;
  148.       case TXT:        /* Graphics request */
  149.         msgcost[i].txt = (TxtCost *) malloc(TXTSLOTS * sizeof(TxtCost));
  150.         for (j = 0; j < TXTSLOTS; j++) {
  151.         /*
  152.         msgcost[i].txt[j].fontname = NULL;
  153.         */
  154.         msgcost[i].txt[j].costlist = NULL;
  155.         }
  156.         break;
  157.       default:
  158.         fprintf(stderr,"init_msgcost: Unknown Message Class: %d for message %s\n",
  159.                 RequestType[i].msgclass, RequestType[i].name);
  160.         break;
  161.     }
  162.     }
  163. }
  164.  
  165. fill_win_cost(req_num, strptrptr)
  166. int req_num;
  167. char **strptrptr;    /* Address of the pointer to the string */
  168. {
  169.     float   size, speed;
  170.  
  171.     /*
  172.      * First get rid of the request name
  173.      */
  174.     while (isspace(**strptrptr))     /* Strip leading white space */
  175.     (*strptrptr)++;
  176.     while (!isspace(**strptrptr))    /* Get past request name */
  177.     (*strptrptr)++;
  178.  
  179.     /* Now search for the window attributes */
  180.     /* There aren't any :-) */
  181.  
  182.     /* Scan the input list of (size, speed) */
  183.     while ( (*strptrptr = strchr(*strptrptr, '(' )) != NULL) {
  184.     if (sscanf(*strptrptr, "(%f, %f)", &size, &speed) != 2) {
  185.        fprintf(stderr,"line %3d: Insufficient arguments\n",linenum);
  186.        fprintf(stderr, "\t%s\n", *strptrptr);
  187.        continue;
  188.     }
  189.     insert_costcell(&msgcost[req_num].win, size, speed);
  190.     (*strptrptr)++;
  191.     }
  192. }
  193.  
  194. /*
  195.  * fill_gfx_cost()
  196.  * Input format expected:
  197.  * Request_Name gxmode=<GXMODE> linestyle=<LINESTYLE> fillstyle=<FILLSTYLE> \
  198.           linewidth=<LINEWIDTH> (Size_1, Speed_1) ... (Size_N, Speed_N)
  199.  *
  200.  */
  201. fill_gfx_cost(req_num, strptrptr)
  202. int req_num;
  203. char **strptrptr;    /* Address of the pointer to the string */
  204. {
  205.     int     gfxindex=0;
  206.     float   size, speed;
  207.     int     gxmode=0, linestyle=0, fillstyle=0, linewidth=0;
  208.     int     fd_all=0;
  209.     Boolean fd_gxmode=FALSE,    fd_linestyle=FALSE,
  210.         fd_fillstyle=FALSE, fd_linewidth=FALSE;
  211.  
  212.     /*
  213.      * First get rid of the request name
  214.      */
  215.     while (isspace(**strptrptr))     /* Strip leading white space */
  216.     (*strptrptr)++;
  217.     while (!isspace(**strptrptr))    /* Get past request name */
  218.     (*strptrptr)++;
  219.  
  220.     /* Now search for the graphics attributes */
  221.     while(fd_all < 4) {
  222.     /* Strip leading white space */
  223.     while (isspace(**strptrptr))
  224.         (*strptrptr)++;
  225.  
  226.     /*
  227.      * Fill the gxmode attribute
  228.      */
  229.     if ( (fd_gxmode == FALSE) && (t_search(*strptrptr, "gxmode=") !=0) ) {
  230.         fd_gxmode = TRUE; fd_all ++;
  231.         while (*(*strptrptr)++ != '='); /* Consume chars upto '=' */
  232.  
  233.         /* Now find out exactly what gxmode it is */
  234.         if      (t_search(*strptrptr, "GXclear") != 0) 
  235.             gxmode = XPROF_GXCLEAR;
  236.         else if (t_search(*strptrptr, "GXand") != 0) 
  237.             gxmode = XPROF_GXAND;
  238.         else if (t_search(*strptrptr, "GXandReverse") != 0) 
  239.             gxmode = XPROF_GXANDREVERSE;
  240.         else if (t_search(*strptrptr, "GXcopy") != 0) 
  241.             gxmode = XPROF_GXCOPY;
  242.         else if (t_search(*strptrptr, "GXandInverted") != 0) 
  243.             gxmode = XPROF_GXANDINVERTED;
  244.         else if (t_search(*strptrptr, "GXnoop") != 0) 
  245.             gxmode = XPROF_GXNOOP;
  246.         else if (t_search(*strptrptr, "GXxor") !=0 )
  247.         gxmode = XPROF_GXXOR;
  248.         else if (t_search(*strptrptr, "GXor") !=0 )
  249.         gxmode = XPROF_GXOR;
  250.         else if (t_search(*strptrptr, "GXnor") != 0) 
  251.             gxmode = XPROF_GXNOR;
  252.         else if (t_search(*strptrptr, "GXequiv") != 0) 
  253.             gxmode = XPROF_GXEQUIV;
  254.         else if (t_search(*strptrptr, "GXinvert") != 0) 
  255.             gxmode = XPROF_GXINVERT;
  256.         else if (t_search(*strptrptr, "GXorReverse") != 0) 
  257.             gxmode = XPROF_GXORREVERSE;
  258.         else if (t_search(*strptrptr, "GXcopyInverted") != 0) 
  259.             gxmode = XPROF_GXCOPYINVERTED;
  260.         else if (t_search(*strptrptr, "GXorInverted") != 0) 
  261.             gxmode = XPROF_GXORINVERTED;
  262.         else if (t_search(*strptrptr, "GXnand") != 0) 
  263.             gxmode = XPROF_GXNAND;
  264.         else if (t_search(*strptrptr, "GXset") != 0) 
  265.             gxmode = XPROF_GXSET;
  266.  
  267.         while (!isspace(**strptrptr))    /* Get past gxmode attribute */
  268.         (*strptrptr)++;
  269.     }
  270.     /*
  271.      * Fill the linestyle attribute
  272.      */
  273.     else 
  274.     if ( (fd_linestyle == FALSE)&&(t_search(*strptrptr,"linestyle=") !=0) ){
  275.         fd_linestyle = TRUE; fd_all ++;
  276.         while (*(*strptrptr)++ != '='); /* Consume chars upto '=' */
  277.  
  278.         if      (t_search(*strptrptr, "LineSolid") != 0) 
  279.             linestyle = XPROF_LINESOLID;
  280.         else if (t_search(*strptrptr, "LineOnOffDash") != 0) 
  281.             linestyle = XPROF_LINEONOFFDASH;
  282.         else if (t_search(*strptrptr, "LineDoubleDash") != 0) 
  283.             linestyle = XPROF_LINEDOUBLEDASH;
  284.  
  285.         while (!isspace(**strptrptr))     /* Get past linestyle attribute */
  286.         (*strptrptr)++;
  287.     }
  288.     /*
  289.      * Fill the fillstyle attribute
  290.      */
  291.     else 
  292.     if ( (fd_fillstyle == FALSE)&&(t_search(*strptrptr, "fillstyle=")!=0)){
  293.         fd_fillstyle = TRUE; fd_all ++;
  294.         while (*(*strptrptr)++ != '='); /* Consume chars upto '=' */
  295.  
  296.         if      (t_search(*strptrptr, "FillSolid") != 0) 
  297.             fillstyle = XPROF_FILLSOLID;
  298.         else if (t_search(*strptrptr, "FillOpaqueStippled") != 0) 
  299.             fillstyle = XPROF_FILLOPAQUESTIPPLED;
  300.         else if (t_search(*strptrptr, "FillStippled") != 0) 
  301.             fillstyle = XPROF_FILLSTIPPLED;
  302.         else if (t_search(*strptrptr, "FillTiled") != 0) 
  303.             fillstyle = XPROF_FILLTILED;
  304.  
  305.         while (!isspace(**strptrptr))     /* Get past fillstyle attribute */
  306.         (*strptrptr)++;
  307.     }
  308.     /*
  309.      * Fill the linewidth attribute
  310.      */
  311.     else 
  312.     if ( (fd_linewidth == FALSE)&&(t_search(*strptrptr, "linewidth=")!=0)){
  313.         int lw;    /* actual line width */
  314.  
  315.         fd_linewidth = TRUE; fd_all ++;
  316.         while (*(*strptrptr)++ != '='); /* Consume chars upto '=' */
  317.  
  318.         sscanf(*strptrptr,"%d", &lw);
  319.         /* Get index of this linewidth*/
  320.         linewidth=get_db_linewidth_index(lw, INSTALL);
  321.         if (linewidth == -1) {
  322.         fprintf(stderr, "line %3d: Cannot add linewidth %d to database",
  323.                     linenum, lw);
  324.         fprintf(stderr, "line %3d: %s", linenum, *strptrptr);
  325.         return;
  326.         } 
  327.          while (!isspace(**strptrptr))     /* Get past linewidth attribute */
  328.          (*strptrptr)++;
  329.     }
  330.     else {
  331.         fprintf(stderr, "line %3d: Cannot parse attributes :%s\n",
  332.         linenum, *strptrptr);
  333.         fflush(stderr);
  334.         return;
  335.     }
  336.     }
  337.     gfxindex = GFXINDEX(gxmode, linestyle, fillstyle, linewidth);
  338.     /*
  339.      * Scan the input list of (size, speed)
  340.      */
  341.     while ( (*strptrptr = strchr(*strptrptr, '(' )) != NULL) {
  342.     if (sscanf(*strptrptr, "(%f, %f)", &size, &speed) != 2) {
  343.        fprintf(stderr,"line %3d: Insufficient arguments\n",linenum);
  344.        fprintf(stderr, "\t%s\n", *strptrptr);
  345.        continue;
  346.     }
  347.     insert_costcell(&msgcost[req_num].gfx[gfxindex].costlist,size,speed);
  348.     (*strptrptr)++;
  349.     }
  350.  
  351. /*
  352. printf("%-17s %2d\n", RequestType[req_num].name, req_num);
  353. printf("Gfxslot = %d", gfxindex);
  354. printlist(msgcost[req_num].gfx[gfxindex].costlist);
  355. fflush(stdout);
  356. */
  357. }
  358.  
  359. fill_txt_cost(req_num, strptrptr)
  360. int req_num;
  361. char **strptrptr;    /* Address of the pointer to the string */
  362. {
  363.     char  buffer[MAXSTRINGSIZE];
  364.     int   txtindex=0;
  365.     float size, speed;
  366.  
  367.     /*
  368.      * First get rid of the request name
  369.      */
  370.     while (isspace(**strptrptr))     /* Strip leading white space */
  371.     (*strptrptr)++;
  372.     while (!isspace(**strptrptr))    /* Get past request name */
  373.     (*strptrptr)++;
  374.  
  375.     /* Now search for the text attributes */
  376.     while (isspace(**strptrptr))     /* Strip leading white space */
  377.     (*strptrptr)++;
  378.  
  379.     if (t_search(*strptrptr, "fontname=") !=0 ) {
  380.     while (*(*strptrptr)++ != '='); /* Consume chars upto '=' */
  381.  
  382.     sscanf(*strptrptr, "%s", buffer);
  383.     txtindex = get_db_fontname_index(buffer);
  384.     if (txtindex == -1) {
  385.         fprintf(stderr, "line %3d: Cannot add font %s to database",
  386.          linenum, buffer);
  387.         fprintf(stderr, "line %3d: %s", linenum, *strptrptr);
  388.         return;
  389.     }
  390.     }
  391.  
  392.     /* Scan the input list of (size, speed) */
  393.     while ( (*strptrptr = strchr(*strptrptr, '(' )) != NULL) {
  394.     if (sscanf(*strptrptr, "(%f, %f)", &size, &speed) != 2) {
  395.        fprintf(stderr,"line %3d: Insufficient arguments\n",linenum);
  396.        fprintf(stderr, "\t%s\n", *strptrptr);
  397.        continue;
  398.     }
  399.     insert_costcell(&msgcost[req_num].txt[txtindex].costlist, size, speed);
  400.     (*strptrptr)++;
  401.     }
  402. }
  403.  
  404. insert_costcell(costlist, size, speed)
  405. CostCell **costlist;    /* Pointer to the costlist */
  406. float size;
  407. float speed;
  408. {
  409.     CostCell *newcell, *listptr;
  410.  
  411.     newcell = allocCostCell(size, speed);
  412.     if (*costlist == NULL) {    /* First time info seen !!*/
  413.     *costlist = newcell;
  414.     }
  415.     else {     /* Insert in linked list in ascending order of size */
  416.     listptr = *costlist;
  417.     while (listptr->nextcost != NULL) {  /* Traverse linked list */
  418.         if ((listptr->size <= newcell->size) &&
  419.         (listptr->nextcost->size >= newcell->size ))
  420.             break;
  421.         listptr = listptr->nextcost;     /* Next item in the list */
  422.     }
  423.     /* Now insert the newcell in the list */
  424.     if (listptr->nextcost == NULL)         /* End of the list */
  425.         listptr->nextcost = newcell;
  426.     else {
  427.         newcell->nextcost  = listptr->nextcost;
  428.         listptr->nextcost = newcell;
  429.     }
  430.     }
  431.  
  432. }
  433.  
  434. float get_request_time(req_num, attributes)
  435. int req_num;
  436. Xattributes *attributes;
  437. {
  438.     CostCell *listptr1, *listptr2;
  439.     float    size1, size2, time1, time2;
  440.     int      gfxindex=0, txtindex=0;
  441.  
  442. #ifdef TEST    
  443.     printlist (msgcost[req_num].win);
  444. #endif
  445.  
  446.     switch(RequestType[req_num].msgclass) {
  447.       case WIN:
  448.     listptr1 = msgcost[req_num].win;
  449.     break;
  450.       case GFX:
  451.     if (attributes->gcval != NULL)
  452.         gfxindex = gc_gfxindex(stdout, req_num, attributes->gcval);
  453. fflush(stdout);
  454.     listptr1 = msgcost[req_num].gfx[gfxindex].costlist;
  455.     break;
  456.       case TXT:
  457.     if (attributes->gcval != NULL)
  458.         txtindex = gc_fontindex(stdout, req_num, attributes->gcval);
  459.     listptr1 = msgcost[req_num].txt[txtindex].costlist;
  460.     break;
  461.       default:
  462.     break;
  463.     }
  464.  
  465.     /* Empty list ? */
  466.     if (listptr1 == NULL)
  467.     return(-1.0);
  468.  
  469.     /* Only one data point ? */
  470.     if (listptr1->nextcost == NULL) {
  471.     if (listptr1->size == 0)
  472.         return (1/listptr1->speed);
  473.     else
  474.         return(attributes->size / (listptr1->size * listptr1->speed));
  475.     }
  476.  
  477.     /* Two or more data points available */
  478.     listptr2 = listptr1->nextcost;
  479.     while ((listptr2->nextcost != NULL)&&(listptr2->size < attributes->size) ) {
  480.     listptr1 = listptr2;
  481.     listptr2 = listptr2->nextcost;
  482.     }
  483.     if (listptr2->size == attributes->size)    /* Exact match !! */
  484.     return(1.0 / listptr2->speed);
  485.  
  486.     if (listptr1->size == attributes->size)    /* Exact match !! */
  487.     return(1.0 / listptr1->speed);
  488.  
  489.     if (listptr2->size != listptr1->size) {    /* Interpolate the msmt. */
  490.     size1 = listptr1->size;
  491.     size2 = listptr2->size;
  492.     time1 = 1.0 / listptr1->speed;
  493.     time2 = 1.0 / listptr2->speed;
  494.  
  495.         return(time1 + ((time2 - time1) / (size2 - size1)) * (attributes->size - size1));
  496.     }
  497.     else return((listptr2->size / attributes->size) * listptr2->speed);
  498. }
  499.  
  500.  
  501. CostCell *allocCostCell(size, speed)
  502. float size;
  503. float speed;
  504. {
  505.     CostCell *newptr;
  506.     
  507.     newptr = (CostCell *) malloc( sizeof(CostCell) );
  508.         
  509.     newptr->size     = size;
  510.     newptr->speed    = speed;
  511.     newptr->nextcost = NULL;
  512.     return (newptr);
  513. }
  514.  
  515. printlist(costlist)
  516. CostCell *costlist;
  517. {
  518.     int count = 0;
  519.  
  520.     while (costlist !=NULL) {
  521.     if (((count % 2) == 0) && (count !=0))
  522.         printf("\n%17s    "," ");
  523.     printf(" (%8.1f,%8.1f,%8.4f)", costlist->size, costlist->speed,
  524.                     1000.0/costlist->speed);
  525.     costlist = costlist->nextcost;
  526.     count++;
  527.     }
  528.     printf("\n");
  529. }
  530.  
  531. static int line_width[XPROF_LINEWIDTHS];
  532. static int num_valid_lw=0;
  533.  
  534. int get_db_linewidth_index(lw, install)
  535. int lw;            /* Actual value of the line width */
  536. Install install;    /* Install in list if not found ? */
  537. {
  538.     int i, retval;
  539.  
  540.     for (i=0; i < num_valid_lw; i++)
  541.     if (lw == line_width[i]) return (i);
  542.     if ( (num_valid_lw == XPROF_LINEWIDTHS)  || (install == NOINSTALL) )
  543.     return (-1);
  544.     retval = num_valid_lw;
  545.     line_width[num_valid_lw++] = lw;
  546.     return (retval);
  547. }
  548.  
  549. /*
  550.  * The following function returns the line width closest to the desired one
  551.  */
  552. int get_db_closest_lw(lw)
  553. int lw;            /* Actual value of the line width */
  554. {
  555.     int i, olderror=MAXINT, error, retval;
  556.  
  557.     if (num_valid_lw == 0)    /* List is empty */
  558.     return (-1);
  559.  
  560.     for (i=0; i < num_valid_lw; i++) {
  561.     error = line_width[i] - lw;
  562.     if (error < 0)
  563.         error *= -1;
  564.     if (error < olderror) {
  565.         retval = line_width[i];
  566.     }
  567.     olderror = error;
  568.     }
  569.     return(retval);
  570. }
  571.  
  572. static char *font_name[TXTSLOTS];
  573. static int  num_valid_fonts=0;
  574.  
  575. int get_db_fontname_index(fontname, install)
  576. char *fontname;        /* Actual name of this font */
  577. Install install;    /* Install in list if not found ? */
  578. {
  579.     int i, retval; 
  580.  
  581.     for (i=0; i < num_valid_fonts; i++)
  582.     if (!strcmp(fontname, font_name[i]) )return(i);
  583.     if ( (num_valid_fonts == TXTSLOTS) || (install == NOINSTALL) )
  584.     return (-1);
  585.     retval = num_valid_fonts;
  586.     font_name[num_valid_fonts] = malloc(strlen(fontname)  + 1);
  587.     strcpy(font_name[num_valid_fonts], fontname);
  588.     num_valid_fonts ++;
  589.     return (retval);
  590. }
  591.  
  592. char *db_font_name(index)
  593. int index;
  594. {
  595.     if (index < num_valid_fonts)
  596.     return(font_name[index]);
  597.     else
  598.     return(NULL);
  599. }
  600.  
  601. #ifdef TEST
  602. main()
  603. {
  604.     FILE *fp;
  605.     int index, size;
  606.     Xattributes attributes;
  607.     float time;
  608.  
  609.     fp = fopen("test.dat", "r");
  610.     parse_parameters(fp);
  611.     while(1) {
  612.     scanf("%d %d", &index, &size);
  613. printf("index = %d size = %d ", index, size); fflush(stdout);
  614.     attributes.size = (float) size;
  615.     time = get_request_time(index, &attributes);
  616.     printf("Time = ");
  617.     if (time == -1)
  618.          printf("N/A\n");
  619.     else printf("%.6f ms\n",time*1000);
  620.     fflush(stdout);
  621.     }
  622. }
  623.  
  624. #endif
  625.